﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using CommonLibrary.Data.GenTimeIdClass;
using Excel = Microsoft.Office.Interop.Excel;

namespace CommonLibrary
{
    public static class SystemHelper
    {
        #region 运行外部命令ShellAndWait、DosCheckString、WinExec
        #region 结构
        [StructLayout(LayoutKind.Sequential)]
        public struct STARTUPINFO
        {
            public int cb;
            public string lpReserved;
            public string lpDesktop;
            public int lpTitle;
            public int dwX;
            public int dwY;
            public int dwXSize;
            public int dwYSize;
            public int dwXCountChars;
            public int dwYCountChars;
            public int dwFillAttribute;
            public int dwFlags;
            public int wShowWindow;
            public int cbReserved2;
            public byte lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public int dwProcessId;
            public int dwThreadId;
        }

        [StructLayout(LayoutKind.Sequential)]
        public class SECURITY_ATTRIBUTES
        {
            public int nLength;
            public string lpSecurityDescriptor;
            public bool bInheritHandle;
        }
        #endregion

        #region 引用
        [DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
        public static extern bool CreateProcess(StringBuilder lpApplicationName, StringBuilder lpCommandLine,
                                                                    SECURITY_ATTRIBUTES lpProcessAttributes,
                                                                    SECURITY_ATTRIBUTES lpThreadAttributes,
                                                                    bool bInheritHandles,
                                                                    int dwCreationFlags,
                                                                    StringBuilder lpEnvironment,
                                                                    StringBuilder lpCurrentDirectory,
                                                                    ref STARTUPINFO lpStartupInfo,
                                                                    ref PROCESS_INFORMATION lpProcessInformation
                                                                    );

        [DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
        public static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);

        [DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
        public static extern bool CloseHandle(IntPtr hObject);

        /// <summary>
        /// WinExec
        /// </summary>
        /// <param name="CmdLine"></param>
        /// <param name="uCmdShow"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll")]
        public static extern bool WinExec(string CmdLine, int uCmdShow);


        #endregion

        /// <summary>
        /// ShellAndWait
        /// </summary>
        /// <param name="in_command"></param>
        /// <param name="in_style"></param>
        /// <returns></returns>
        public static bool ShellAndWait(string in_command, int in_style)
        {

            try
            {
                StringBuilder sbCommand = new StringBuilder(4000);
                sbCommand.Append(in_command);

                STARTUPINFO sInfo = new STARTUPINFO();
                sInfo.dwFlags = 1;

                if (in_style == 0)
                {
                    if (IntPtr.Size == 4)
                    {
                        sInfo.wShowWindow = 0;
                    }
                    else
                    {
                        //64位系统的隐藏为 1
                        sInfo.wShowWindow = 1;
                    }
                }
                else
                {
                    if (in_style == 1)
                    {
                        if (IntPtr.Size == 4)
                        {
                            sInfo.wShowWindow = 1;
                        }
                        else
                        {
                            //64位系统的隐藏为 1
                            sInfo.wShowWindow = 0;
                        }
                    }
                    else
                    {
                        sInfo.wShowWindow = in_style;
                    }
                }


                PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();

                if (!CreateProcess(null, sbCommand, null, null, false, 0, null, null, ref sInfo, ref pInfo))
                {
                    return false;
                }
                WaitForSingleObject(pInfo.hProcess, 600000000);
                CloseHandle(pInfo.hProcess);
                CloseHandle(pInfo.hThread);
                return true;
            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
                Console.ReadKey();
                return false;
            }

        }

        /// <summary>
        /// ClRunAsDos
        /// </summary>
        /// <param name="dosLine"></param>
        /// <param name="checkString"></param>
        /// <returns></returns>
        public static bool ClRunAsDos(this string dosLine, string checkString)
        {
            bool Flag = false;
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            try
            {
                proc.StartInfo.FileName = "cmd.exe";
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.RedirectStandardInput = true;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.CreateNoWindow = true;
                proc.Start();
                proc.StandardInput.WriteLine(dosLine);
                proc.StandardInput.WriteLine("exit");
                string pingResult = proc.StandardOutput.ReadToEnd();
                proc.WaitForExit();
                if (pingResult.IndexOf(checkString) != -1)
                {
                    //找到
                    Flag = true;
                }
                proc.StandardOutput.Close();
            }
            catch
            { }
            finally
            {
                try
                {
                    proc.Close();
                    proc.Dispose();
                }
                catch
                {
                }
            }
            return Flag;
        }

        /// <summary>
        /// ClRunAsDos
        /// </summary>
        /// <param name="dosLine"></param>
        /// <param name="outString"></param>
        public static void ClRunAsDos(this string dosLine, out string outString)
        {
            outString = null;
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            try
            {
                proc.StartInfo.FileName = "cmd.exe";
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.RedirectStandardInput = true;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.CreateNoWindow = true;
                proc.Start();
                proc.StandardInput.WriteLine(dosLine);
                proc.StandardInput.WriteLine("exit");
                string pingResult = proc.StandardOutput.ReadToEnd();
                proc.WaitForExit();

                outString = pingResult;
                proc.StandardOutput.Close();
            }
            catch
            { }
            finally
            {
                try
                {
                    proc.Close();
                    proc.Dispose();
                }
                catch
                {
                }
            }
        }

        /// <summary>
        /// ClRunAsDos
        /// </summary>
        /// <param name="dosLine"></param>
        public static void ClRunAsDos(this string dosLine)
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            try
            {
                proc.StartInfo.FileName = "cmd.exe";
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.RedirectStandardInput = true;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.CreateNoWindow = true;
                proc.Start();
                proc.StandardInput.WriteLine(dosLine);
                proc.StandardInput.WriteLine("exit");
                string pingResult = proc.StandardOutput.ReadToEnd();
                proc.WaitForExit();

                proc.StandardOutput.Close();
            }
            catch
            { }
            finally
            {
                try
                {
                    proc.Close();
                    proc.Dispose();
                }
                catch
                {
                }
            }
        }

        #endregion

        /// <summary>
        /// 获取计算机名
        /// </summary>
        /// <returns></returns>
        public static string GetMachineName()
        {
            return Environment.MachineName;
        }

        #region GUID

        /// <summary>
        /// 获取GUID
        /// </summary>
        /// <returns></returns>
        public static string GetNewID()
        {
            return Guid.NewGuid().ToString().ToUpper();
        }

        /// <summary>
        /// ClGuid，如8D7EA0D9-D174-4D6A-A449-066BE6F0961C,36位
        /// </summary>
        /// <param name="in_str"></param>
        /// <returns></returns>
        public static string ClGuid(this string in_str)
        {
            if (in_str.ClIsNullOrWhiteSpace())
            {
                return GetNewID();
            }
            return (new Guid(in_str)).ToString().ToUpper();
        }

        /// <summary>
        /// String To Guid
        /// </summary>
        /// <param name="in_str"></param>
        /// <returns></returns>
        public static Guid ClToGuid(this string in_str)
        {
            if (in_str.ClIsNullOrWhiteSpace())
            {
                return Guid.NewGuid();
            }
            return (new Guid(in_str));
        }


        /// <summary>
        /// 获取Oracle的sys_guid()
        /// </summary>
        /// <returns></returns>
        public static string GetSysGuid()
        {
            return GetNewID().Replace("-", "");
        }

        /// <summary>
        /// guid,去除连接符"-"，如：8D7EA0D9D1744D6AA449066BE6F0961C，32位
        /// </summary>
        /// <param name="in_str"></param>
        /// <returns></returns>
        public static string ClSysGuid(this string in_str)
        {
            if (in_str.ClIsNullOrWhiteSpace())
            {
                return GetSysGuid();
            }
            return (new Guid(in_str)).ToString().ToUpper().Replace("-", "");
        }

        #endregion

        /// <summary>
        /// Guid转字符串，按Sql Server的uniqueidentifier排序
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static string GuidToStringByOrder(this Guid guid)
        {
            string str = guid.ToString();//EA6E5CEB-10C5-E311-9275-A30F00B0CE02

            string a = str.Substring(0, 8);//EA6E5CEB
            string b = str.Substring(9, 4);//10C5
            string c = str.Substring(14, 4);//E311
            string d = str.Substring(19, 4);//9275
            string e = str.Substring(24, 12);//A30F00B0CE02

            a = a.ClRight(2) + a.Substring(4, 2) + a.Substring(2, 2) + a.ClLeft(2);//EB5C6EEA
            b = b.ClRight(2) + b.ClLeft(2);//C510
            c = c.ClRight(2) + c.ClLeft(2);//11E3
            string newid = e + d + c + b + a;//A30F00B0CE02927511E3C510EB5C6EEA


            a = newid.Substring(0, 8);//A30F00B0
            b = newid.Substring(8, 4);//CE02
            c = newid.Substring(12, 4);//9275
            d = newid.Substring(16, 4);//11E3
            e = newid.Substring(20, 12);//C510EB5C6EEA

            newid = a + "-" + b + "-" + c + "-" + d + "-" + e;//A30F00B0-CE02-9275-11E3-C510EB5C6EEA
            return newid.ToUpper();
        }


        #region 前6位BINARY修改为时间，后10位为随机数

        /// <summary>
        /// Guid类型，前6位BINARY修改为时间，后10位为随机数
        /// </summary>
        /// <returns></returns>
        public static Guid NewCombId()
        {
            byte[] destinationArray = Guid.NewGuid().ToByteArray();
            DateTime time = new DateTime(0x76c, 1, 1);
            DateTime now = DateTime.Now;
            TimeSpan span = new TimeSpan(now.Ticks - time.Ticks);
            TimeSpan timeOfDay = now.TimeOfDay;
            byte[] bytes = BitConverter.GetBytes(span.Days);
            byte[] array = BitConverter.GetBytes((long)(timeOfDay.TotalMilliseconds / 3.333333));
            Array.Reverse(bytes);
            Array.Reverse(array);
            Array.Copy(bytes, bytes.Length - 2, destinationArray, destinationArray.Length - 6, 2);
            Array.Copy(array, array.Length - 4, destinationArray, destinationArray.Length - 4, 4);
            return new Guid(destinationArray);
        }

        /// <summary>
        /// Guid类型，前6位BINARY修改为时间，后10位为随机数
        /// </summary>
        /// <param name="in_str"></param>
        /// <returns></returns>
        public static string ClGuidComb(this string in_str)
        {
            return NewCombId().ToString().ToUpper();
        }

        /// <summary>
        /// 有顺序的字符串，前6位BINARY修改为时间，后10位为有顺序的Guid
        /// </summary>
        /// <param name="in_str"></param>
        /// <returns></returns>
        public static string ClGuidCombString(this string in_str)
        {
            return GuidToStringByOrder(NewCombId());
        }

        #endregion


        #region 前6位BINARY修改为时间，后10位为有顺序的Guid

        /// <summary>
        /// 计算机不重启时，Guid有顺序
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [DllImport("rpcrt4.dll", SetLastError = true)]
        static extern int UuidCreateSequential(out Guid guid);
        public static Guid NewSequentialId()
        {
            Guid guid;
            UuidCreateSequential(out guid);
            var s = guid.ToByteArray();
            var t = new byte[16];
            t[3] = s[0];
            t[2] = s[1];
            t[1] = s[2];
            t[0] = s[3];
            t[5] = s[4];
            t[4] = s[5];
            t[7] = s[6];
            t[6] = s[7];
            t[8] = s[8];
            t[9] = s[9];
            t[10] = s[10];
            t[11] = s[11];
            t[12] = s[12];
            t[13] = s[13];
            t[14] = s[14];
            t[15] = s[15];
            return new Guid(t);
        }

        /// <summary>
        /// 计算机不重启时，Guid有顺序
        /// </summary>
        /// <param name="in_str"></param>
        /// <returns></returns>
        public static string ClGuidSequence(this string in_str)
        {
            return NewSequentialId().ToString().ToUpper();
        }

        /// <summary>
        /// Guid类型，前6位BINARY修改为时间，后10位为有顺序的Guid
        /// </summary>
        /// <returns></returns>
        public static Guid NewCombSequenceId()
        {
            byte[] destinationArray = NewSequentialId().ToByteArray();
            DateTime time = new DateTime(0x76c, 1, 1);
            DateTime now = DateTime.Now;
            TimeSpan span = new TimeSpan(now.Ticks - time.Ticks);
            TimeSpan timeOfDay = now.TimeOfDay;
            byte[] bytes = BitConverter.GetBytes(span.Days);
            byte[] array = BitConverter.GetBytes((long)(timeOfDay.TotalMilliseconds / 3.333333));
            Array.Reverse(bytes);
            Array.Reverse(array);
            Array.Copy(bytes, bytes.Length - 2, destinationArray, destinationArray.Length - 6, 2);
            Array.Copy(array, array.Length - 4, destinationArray, destinationArray.Length - 4, 4);
            return new Guid(destinationArray);
        }

        /// <summary>
        /// 有顺序的Guid，前6位BINARY修改为时间，后10位为有顺序的Guid，适用于Sql Server的uniqueidentifier字段
        /// </summary>
        /// <param name="in_str"></param>
        /// <returns></returns>
        public static string ClGuidCombSequence(this string in_str)
        {
            return NewCombSequenceId().ToString().ToUpper();
        }

        /// <summary>
        /// 有顺序的字符串，前6位BINARY修改为时间，后10位为有顺序的Guid，适用于Sql Server或Oracle的Varchar(36)
        /// </summary>
        /// <param name="in_str"></param>
        /// <returns></returns>
        public static string ClGuidCombSequenceString(this string in_str)
        {
            Guid guid = NewCombSequenceId();
            return GuidToStringByOrder(guid);
        }

        #endregion









        /// <summary>
        /// 获取时间ID
        /// </summary>
        /// <param name="in_WorkerId"></param>
        /// <param name="in_DatacenterId"></param>
        /// <returns></returns>
        public static long GenTimeId(int in_WorkerId, int in_DatacenterId)
        {
            IdWorker worker = new IdWorker(in_WorkerId, in_DatacenterId);
            return worker.NextId();
        }

        /// <summary>
        /// 获取时间ID
        /// </summary>
        /// <param name="in_WorkerId"></param>
        /// <param name="in_DatacenterId"></param>
        /// <returns></returns>
        public static long GenTimeId(int in_WorkerId)
        {
            return GenTimeId(in_WorkerId, 1);
        }

        /// <summary>
        /// 获取时间ID
        /// </summary>
        /// <returns></returns>
        public static long GenTimeId()
        {
            return GenTimeId(1, 1);
        }

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern int GetShortPathName([MarshalAs(UnmanagedType.LPTStr)] string path, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath, int shortPathLength);


        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern uint GetLongPathName([MarshalAs(UnmanagedType.LPTStr)] string shortname, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder longnamebuff, uint buffersize);


        [DllImport("user32.dll", SetLastError = true)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
        public static void KillExcel(Excel.Application xlApp)
        {
            IntPtr t = new IntPtr(xlApp.Hwnd);   //得到这个句柄，具体作用是得到这块内存入口 

            int k = 0;
            GetWindowThreadProcessId(t, out k);   //得到本进程唯一标志k
            System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k);   //得到对进程k的引用
            p.Kill();     //关闭进程k
        }


        /// <summary>
        /// 获取空闲的线程
        /// </summary>
        /// <param name="threads"></param>
        /// <returns></returns>
        public static int GetFreeThread(Thread[] threads)
        {
            int threadIndex;
            while (true)
            {
                for (threadIndex = 0; threadIndex < threads.Length; threadIndex++)
                {
                    if (threads[threadIndex] == null)
                    {
                        break;
                    }

                    if (threads[threadIndex].IsAlive == false)
                    {
                        break;
                    }
                }

                if (threadIndex < threads.Length)
                {
                    break;
                }
                Thread.Sleep(10);
            }

            return threadIndex;
        }

        /// <summary>
        /// 判断所有的线程是否已经完成
        /// </summary>
        /// <param name="threads"></param>
        public static void CheckThreadComplete(Thread[] threads)
        {
            while (true)
            {
                bool isBusy = false;
                for (int i = 0; i < threads.Length; i++)
                {
                    if (threads[i] == null)
                    {
                        continue;
                    }
                    if (threads[i].IsAlive)
                    {
                        isBusy = true;
                        break;
                    }
                }

                if (isBusy == false)
                {
                    break;
                }

                Thread.Sleep(10);
            }
        }


        /// <summary>
        /// 互斥锁
        /// </summary>
        /// <param name="in_List"></param>
        /// <returns></returns>
        public static List<Mutex> MutexLock(List<string> in_List)
        {
            List<string> list = new List<string>();
            foreach (string str in in_List)
            {
                list.Add(str);
            }
            list.Sort();

            List<Mutex> listMutex = new List<Mutex>();
            foreach (string str in list)
            {
                Mutex mutex = new Mutex(false, str.Trim().ToUpper());//false：是否要等其它调用的进程结束！！！
                mutex.WaitOne();//等待其它m释放
                listMutex.Add(mutex);
            }
            return listMutex;
        }

        /// <summary>
        /// 互斥锁
        /// </summary>
        /// <param name="arr"></param>
        /// <returns></returns>
        public static List<Mutex> MutexLock(params string[] arr)
        {
            List<string> list = new List<string>();
            foreach (string str in arr)
            {
                list.Add(str);
            }

            return MutexLock(list);
        }

        /// <summary>
        /// 删除互斥锁
        /// </summary>
        /// <param name="listMutex"></param>
        public static void MutexFree(this List<Mutex> listMutex)
        {
            foreach (Mutex mutex in listMutex)
            {
                try
                {
                    mutex.ReleaseMutex();
                    mutex.Close();
                }
                catch { }

            }

        }

        /// <summary>
        /// 读取硬盘序列号
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public static string GetSerialNumber(byte index)
        {
            return CommonLibrary.Other.GetSerialNumberClass.GetSerialNumber(index);
        }

        /// <summary>
        /// 读取硬盘序列号
        /// </summary>
        /// <returns></returns>
        public static string GetSerialNumber()
        {
            return GetSerialNumber(0);
        }

    }
}
